using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using System.Text;
using Microsoft.SharePoint.WebPartPages;
using System.Diagnostics;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Navigation;
using System.Configuration;
using Microsoft.Office.Server.UserProfiles;
using Microsoft.Office.Server;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Web;
using System.Security.Principal;
using Microsoft.Office.Server.ActivityFeed;
using System.Collections;
using eGov.SharePoint.MyPeeps.EventReceivers;

namespace eGov.SharePoint.MyPeeps.MySiteCustomization.Features.MySiteCustomizations
{
    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>

    [Guid("db9e0e76-4156-4fa9-8719-a35b1954f339")]
    public class MySiteCustomizationsEventReceiver : SPFeatureReceiver
    {
        private SPWeb currentWeb = null;
        private const string CUSTOMMASTERPAGENAME = "custommaster.master";
        private const string DEFAULTMASTERPAGENAME = "v4.master";
        private string KEY_CHK = Properties.Settings.Default.PartCheckKey;

        #region ULS Prep

        private SPDiagnosticsArea logArea;
        private SPDiagnosticsService logService = SPDiagnosticsService.Local;
        protected SPDiagnosticsArea LogArea
        {
            get
            {
                if (this.logArea == null)
                    this.logArea = new SPDiagnosticsArea("eGov.SharePoint.MyPeeps", new List<SPDiagnosticsCategory>
                    { 
                        new SPDiagnosticsCategory("MySiteCustomizationsEventReceiver", TraceSeverity.High, EventSeverity.Error),
                        new SPDiagnosticsCategory("MySiteCustomizationsEventReceiver", TraceSeverity.Verbose, EventSeverity.Information) 
                    });
                return this.logArea;
            }
        }
        protected SPDiagnosticsCategory logCategory_Error
        {
            // Indexing if used starts from 1
            get { return this.LogArea.Categories[1]; }
        }
        protected SPDiagnosticsCategory logCategory_Information
        {
            // Indexing if used starts from 1
            get { return this.LogArea.Categories[2]; }
        }

        #endregion

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSite mysite = properties.Feature.Parent as SPSite;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                currentWeb = mysite.OpenWeb();
                if (currentWeb.WebTemplate == "SPSPERS")
                {
                    StringBuilder str = new StringBuilder();
                    EventLog eventlog = new EventLog();
                    eventlog.Source = "MySite Customization Feature";
                    currentWeb.AllowUnsafeUpdates = true;
                    mysite.AllowUnsafeUpdates = true;
                    try
                    {
                        eventlog.WriteEntry("Starting Activation of the MySite Customization Feature, SiteURL: " + currentWeb.Url);
                        currentWeb.Description = "MySite :: " + DateTime.Now.ToShortDateString();

                        CreateFolloweRequestList();
                        AddMyLinks(mysite);

                        //Reset Custom pages for dynamic webpart additions by the PartCheck Class
                        ResetPagePartCheckKey(currentWeb, "mypeeps.aspx");
                        ResetPagePartCheckKey(currentWeb, "ViewAllActivity.aspx");

                        //Moved to PartCheck, on site creation the lists(shared docs and shared pics) exists only after the feature is activated
                        //this.EnsureSharedListsFeedSettings(currentWeb, true, eventlog, "Activating");

                        eventlog.WriteEntry("Succesfull Activation of the MySite Customization Feature, SiteURL: " + currentWeb.Url);
                        logService.WriteTrace(100, logCategory_Information, TraceSeverity.Verbose, "Feature activated.", null);
                    }
                    catch (Exception e)
                    {
                        logService.WriteTrace(100, logCategory_Error, TraceSeverity.High,
                           String.Format("Feature failed on activation. Exception message: {0} \r\n Stack Trace: \r\n {1}", new object[] { e.Message, e.StackTrace }), null);


                        eventlog.WriteEntry(String.Format("Error activating MySite Customization feature {0} : ", e.ToString()), EventLogEntryType.Error);
                    }
                    finally
                    {
                        currentWeb.Update();
                        currentWeb.AllowUnsafeUpdates = false;
                        mysite.AllowUnsafeUpdates = false;
                    }
                }
            });
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSite mysite = properties.Feature.Parent as SPSite;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                currentWeb = mysite.OpenWeb();
                StringBuilder str = new StringBuilder();
                EventLog eventlog = new EventLog();
                eventlog.Source = "MySite Customization Feature - Deactivating";
                if (currentWeb.WebTemplate == "SPSPERS")
                {
                    eventlog.WriteEntry("Starting De-Activation of the MySite Customization Feature: SiteUrl:" + currentWeb.Url);
                    currentWeb.AllowUnsafeUpdates = true;
                    mysite.AllowUnsafeUpdates = true;
                    try
                    {
                        #region Retract feature Assets
                        //Reset PartCheck property: Property that flags the pages for the addition of the custom webparts the first time the page is visited)
                        //currentWeb.Properties.Remove(KEY_CHK);

                        #region Delete Files added by Feature
                        for (int i = 0; i < currentWeb.RootFolder.Files.Count - 1; i++)
                        {
                            if (currentWeb.RootFolder.Files[i].Name.ToLower().Contains("custom-peeps"))
                            {
                                currentWeb.RootFolder.Files[i].Delete();
                                continue;
                            }
                            if (currentWeb.RootFolder.Files[i].Name.ToLower().Contains("mypeeps"))
                            {
                                currentWeb.RootFolder.Files[i].Delete();
                                continue;
                            }
                            if (currentWeb.RootFolder.Files[i].Name.ToLower().Contains("myupdates"))
                            {
                                currentWeb.RootFolder.Files[i].Delete();
                                continue;
                            }
                            if (currentWeb.RootFolder.Files[i].Name.ToLower().Contains("viewallactivity"))
                            {
                                currentWeb.RootFolder.Files[i].Delete();
                                continue;
                            }
                        }
                        #endregion

                        #region Delete Custom list
                        Guid listid = new Guid();
                        foreach (SPList list in currentWeb.Lists)
                        {
                            if (list.Title.ToLower() == "follower requests")
                            {
                                listid = list.ID;
                                break;
                            }
                        }
                        if (listid != new Guid())
                            currentWeb.Lists[listid].Delete();
                        #endregion

                        #region Delete Webparts
                        try
                        {
                            ////Delete webparts added by feature
                            SPList spList = currentWeb.Lists["Web Part Gallery"];
                            if (spList.RootFolder.Files["WhatsOnYourMind.webpart"].Exists)
                                spList.RootFolder.Files["WhatsOnYourMind.webpart"].Delete();
                            if (spList.RootFolder.Files["FollowerRequests.webpart"].Exists)
                                spList.RootFolder.Files["FollowerRequests.webpart"].Delete();
                            if (spList.RootFolder.Files["Following.webpart"].Exists)
                                spList.RootFolder.Files["Following.webpart"].Delete();
                            if (spList.RootFolder.Files["MyPeepsUpdates.webpart"].Exists)
                                spList.RootFolder.Files["MyPeepsUpdates.webpart"].Delete();
                            if (spList.RootFolder.Files["MyUpdatesWebPart.webpart"].Exists)
                                spList.RootFolder.Files["MyUpdatesWebPart.webpart"].Delete();
                            if (spList.RootFolder.Files["ConsolidatedUpdatesWebPart.webpart"].Exists)
                                spList.RootFolder.Files["ConsolidatedUpdatesWebPart.webpart"].Delete();
                            if (spList.RootFolder.Files["PublishedUpdatesWebPart.webpart"].Exists)
                                spList.RootFolder.Files["PublishedUpdatesWebPart.webpart"].Delete();
                            spList.Update();
                        }
                        catch (Exception)
                        {
                            //No action needed, if the deletion of the files is not crucial, it simply is a cleanup action 
                        }
                        #endregion


                        #endregion

                        this.EnsureSharedListsFeedSettings(currentWeb, false, eventlog, "De-Activating");

                        ClearCustomLinks(mysite);

                        eventlog.WriteEntry("Succesfull De-Activation of the MySite Customization Feature, SiteURL: " + currentWeb.Url);
                        logService.WriteTrace(100, logCategory_Information, TraceSeverity.Verbose, "Feature deactivated.", null);
                    }
                    catch (Exception e)
                    {
                        logService.WriteTrace(100, logCategory_Error, TraceSeverity.High,
                           String.Format("Feature failed on deactivation. Exception message: {0} \r\n Stack Trace: \r\n {1}", new object[] { e.Message, e.StackTrace }), null);

                        eventlog.WriteEntry(String.Format("Error de-activating MySite Customization feature {0} : ", currentWeb.Url + " - " + e.ToString()), EventLogEntryType.Error);
                    }
                    finally
                    {
                        currentWeb.Update();
                        currentWeb.AllowUnsafeUpdates = false;
                        mysite.AllowUnsafeUpdates = false;
                    }
                }
            });
        }

        public void CreateFolloweRequestList()
        {
            bool listExists = false;
            foreach (SPList list1 in currentWeb.Lists)
            {
                if (list1.Title == "Follower requests")
                {
                    listExists = true;
                    break;
                }
            }

            if (!listExists)
            {
                //web.AllowUnsafeUpdates = true;
                Guid newListGuid = currentWeb.Lists.Add("Follower requests", "Follower requests", SPListTemplateType.GenericList);

                SPList list = currentWeb.Lists[newListGuid];
                list.OnQuickLaunch = true;
                SPField field;


                list.Fields.Add("Follower", SPFieldType.User, false);
                SPFieldUser fieldUser = (SPFieldUser)list.Fields["Follower"];
                fieldUser.Description = "Follower request";
                fieldUser.Required = false;
                fieldUser.SelectionMode = SPFieldUserSelectionMode.PeopleOnly;
                fieldUser.AllowMultipleValues = false;
                fieldUser.LookupField = "Account";
                //fieldUser.LookupField = "Name";

                fieldUser.Presence = true;

                field = list.Fields.CreateNewField(SPFieldType.Boolean.ToString(), "IsAllowed");
                field.Required = false;
                field.DefaultValue = "false";
                field.Description = "Is allowed to follow me";
                list.Fields.Add(field);

                //Copy settings from the All Items view and then delete the view
                string query = list.Views["All Items"].Query;
                SPViewCollection viewcoll = list.Views;
                Guid viewID = list.Views["All Items"].ID;
                viewcoll.Delete(viewID);

                System.Collections.Specialized.StringCollection viewFields = new System.Collections.Specialized.StringCollection();

                viewFields.Add("Edit");
                viewFields.Add("Follower");
                viewFields.Add("IsAllowed");

                // Add the view to the list
                list.Views.Add("All Items", viewFields, query, 100, true, true);

                // Save the changes
                list.OnQuickLaunch = true;
                list.Update();
            }
            //currentWeb.Update();
        }

        private void AddMyLinks(SPSite mysite)
        {
            try
            {
                UserProfileManager profileManager = new UserProfileManager(SPServiceContext.GetContext(mysite));
                SPUser user = mysite.RootWeb.SiteAdministrators[0];
                UserProfile userProfile = profileManager.GetUserProfile(user.LoginName);

                QuickLink[] links = userProfile.QuickLinks.GetItems(Privacy.Private);
                bool createABlogExists = false;
                bool manageCollExists = false;
                foreach (QuickLink link in links)
                {
                    if (link.Title == "Create a Blog")
                        createABlogExists = true;

                    if (link.Title == "Manage Colleagues")
                        manageCollExists = true;
                }

                //    userProfile.QuickLinks.Create("Create a Blog", mysite.Url + "/_layouts/MySite.aspx?Blog=1", QuickLinkGroupType.General, "Manage My Site", Privacy.Private);         
                string mysiteUrl = profileManager.MySiteHostUrl.TrimEnd(new char[] { '/' });
                mysiteUrl = mysiteUrl + "/";
                mysiteUrl = mysiteUrl + profileManager.PersonalSiteInclusion.Trim(new char[] { '/' });
                mysiteUrl = mysiteUrl + "/";
                string userNameNoDomain = user.LoginName;
                if (user.LoginName.IndexOf("/") > -1)
                    userNameNoDomain = user.LoginName.Substring(user.LoginName.IndexOf("/"));
                mysiteUrl = mysiteUrl + userNameNoDomain;

                if (!createABlogExists)
                    userProfile.QuickLinks.Create("Create a Blog", mysite.Url + "/_layouts/MySite.aspx?Blog=1", QuickLinkGroupType.General, "Manage My Site", Privacy.Private);
                //userProfile.QuickLinks.Create("Create a Blog", mysite.Url + "/_layouts/MySite.aspx?Blog=1", QuickLinkGroupType.General, "Manage My Site", Privacy.Private);
                //userProfile.QuickLinks.Create("Find Colleagues", , QuickLinkGroupType.General, "Manage My Site", Privacy.Private

                if (!manageCollExists)
                    userProfile.QuickLinks.Create("Manage Colleagues", string.Format(mysite.Url + "/_layouts/MyContactLinks.aspx?accountname={0}", user.LoginName), QuickLinkGroupType.General, "Manage My Site", Privacy.Private);

                if (!createABlogExists || !manageCollExists)
                    userProfile.Commit();

            }
            catch (Exception e)
            {
                logService.WriteTrace(100, logCategory_Information, TraceSeverity.Medium,
                              String.Format("My Site Feature failed to add user links. Exception message: {0} \r\n Stack Trace: \r\n {1}", new object[] { e.Message, e.StackTrace }), null);
            }
        }


        private void ClearCustomLinks(SPSite mysite)
        {
            try
            {
                UserProfileManager profileManager = new UserProfileManager(SPServiceContext.GetContext(mysite));
                SPUser user = mysite.RootWeb.SiteAdministrators[0];
                UserProfile userProfile = profileManager.GetUserProfile(user.LoginName);

                QuickLink[] links = userProfile.QuickLinks.GetItems(Privacy.Private);
                Collection<QuickLink> linksToDelete = new Collection<QuickLink>();
                foreach (QuickLink link in links)
                {
                    if (link.Title == "Create a Blog")
                        linksToDelete.Add(link);

                    if (link.Title == "Manage Colleagues")
                        linksToDelete.Add(link);
                }

                foreach (QuickLink l in linksToDelete)
                {
                    userProfile.QuickLinks[l.ID].Delete();
                }
                userProfile.Commit();
            }
            catch (Exception e)
            {
                logService.WriteTrace(100, logCategory_Information, TraceSeverity.Medium,
                              String.Format("My Site Feature failed to clea custom user links. Exception message: {0} \r\n Stack Trace: \r\n {1}", new object[] { e.Message, e.StackTrace }), null);
            }
        }

        private void ResetPagePartCheckKey(SPWeb currentweb, string pageUrl)
        {
            if (currentWeb.Files[pageUrl].Exists)
            {
                SPFile file = currentWeb.Files[pageUrl];
                if (file.Properties[KEY_CHK] != null)
                    file.Properties[KEY_CHK] = null;
                file.Update();
            }
        }

        private void EnsureSharedListsFeedSettings(SPWeb currentWeb, bool enable, EventLog eventlog, string operationTitle)
        {
            if (currentWeb == null) return;
            //SPList sharedDocuments = currentWeb.Lists["Shared Documents"];
            //SPList sharedPictures = currentWeb.Lists["Shared Pictures"];
            SPList sharedDocuments = null;
            SPList sharedPictures = null;
            bool flag_DocumentsEnabled = false, flag_PicturessEnabled = false;

            foreach (SPList list in currentWeb.Lists)
            {
                if (list.Title.ToLower() == "shared documents")
                {
                    sharedDocuments = list;
                    continue;
                }
                else if (list.Title.ToLower() == "shared pictures")
                {
                    sharedPictures = list;
                    continue;
                }
            }

            if (sharedDocuments != null)
                flag_DocumentsEnabled = ContentActionFeedEventReceiver.IsEventReceiverAttached(sharedDocuments);
            else
                eventlog.WriteEntry(String.Format("Warning " + operationTitle + " MySite Customization feature {0} : Could not ensure activity stream condiguration for Shared Documents", currentWeb.Url), EventLogEntryType.Warning);

            if (sharedPictures != null)
                flag_PicturessEnabled = ContentActionFeedEventReceiver.IsEventReceiverAttached(sharedPictures);
            else
                eventlog.WriteEntry(String.Format("Warning " + operationTitle + "  MySite Customization feature {0} : Could not ensure activity stream condiguration for Shared Pictures", currentWeb.Url), EventLogEntryType.Warning);

            if (enable)
            {
                if (!flag_DocumentsEnabled) ContentActionFeedEventReceiver.ActivateServiceOnList(sharedDocuments);
                if (!flag_PicturessEnabled) ContentActionFeedEventReceiver.ActivateServiceOnList(sharedPictures);
            }
            else
            {
                if (flag_DocumentsEnabled) ContentActionFeedEventReceiver.DeactivateServiceOnList(sharedDocuments);
                if (flag_PicturessEnabled) ContentActionFeedEventReceiver.DeactivateServiceOnList(sharedPictures);
            }
        }

    }
}
